#ifdef WIN32

#else
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#endif
#include "ShareMem.h"


CShareMem::CShareMem()
{

	m_hShareMem	= 0;
	m_pShareMemMap = (void*)NULL;
	module_id = -1;
	mem_size = DEFAULT_SIZE;

}

extern int errno;
int CShareMem::Shm_Create(const char* shmName, int size, int *error)
{
	int fd;	
	fd = shm_open(shmName, O_CREAT | O_RDWR | O_EXCL, 0666);
	if(fd<0)
	{
		Loger.printf(LOG_ERROR,"[Shm_Create] create error, name=%s,size=%d\n", shmName, size);
		if(errno==EEXIST)
              {
               	Loger.printf(LOG_ERROR,"[Shm_Create] create error,EEXIST, name=%s,size=%d\n", shmName, size);
			if(error)
				*error = 1;
              }
		return 0;
	}

	if(ftruncate(fd, size) < 0)
	{
			shm_unlink(shmName);
			return 0;
	}
	close(fd);
	mem_size = size;
	Loger.printf(LOG_MSG,"[Shm_Create] create success, name=%s,size=%d\n", shmName, size);
	return 1;
}

int CShareMem::Shm_Delete(const char* shmName)
{
	int result; 
	result = shm_unlink((char*)shmName);
	if(result == -1) 
		return 0;
	return 1;
}

int CShareMem::Shm_Open(const char* shmName, int mode, int type, int size)
{
	Shm_Open(shmName,  mode,  size);
}

int CShareMem::Shm_Open(const char* shmName, int mode, int size)
{
	char share_path[56];
	struct stat tmpStat;
	memset(share_path, 0, sizeof(share_path));
	strcpy(share_path, "/dev/shm/");
	strcat(share_path, shmName);
	if(strlen(share_path)>56-1)
	{
		share_path[56-1] = 0;
	}
	else
	{
		share_path[strlen(share_path)] = 0;
	}

	if(size != -1)
	{
		mem_size = size;
	}
	else
	{
		mem_size = DEFAULT_SIZE;
	}

	if(mode==READ_MODE)
		m_hShareMem=open(share_path, O_RDWR, 0);
	else if(mode==WRITE_MODE)
		m_hShareMem=open(share_path, O_RDWR, 0);
	if(m_hShareMem == -1)
	{
		Loger.printf(LOG_ERROR,"[Shm_Open] open error =%s, shareName=%s\n", strerror(errno),shmName);
		return 0;
	}	
	Loger.printf(LOG_DEBUG,"[Shm_Open] shareName=%s size=%d\n", shmName, mem_size);
	if(ftruncate(m_hShareMem, mem_size) < 0)
	{
		Loger.printf(LOG_ERROR,"[Shm_Open] ftruncate error=%s, shareName=%s, size=%d\n", strerror(errno),shmName, mem_size);
		return 0;
	}
	memset(&tmpStat, 0, sizeof(tmpStat));
	if(fstat(m_hShareMem,&tmpStat) != 0)
	{
		Loger.printf(LOG_ERROR,"[Shm_Open] fstat error=%s, shareName=%s, size=%d\n",strerror(errno),shmName, mem_size);
		return 0;
	}	

	if(tmpStat.st_size != mem_size)
	{
		Loger.printf(LOG_WARNING,"[Shm_Open] tmpStat.st_size[%d] != mem_size[%d]\n", tmpStat.st_size, mem_size);
	}
	
	if(mode==READ_MODE)
		m_pShareMemMap = mmap(NULL,tmpStat.st_size,PROT_READ,MAP_SHARED,m_hShareMem,0);	
	else if(mode==WRITE_MODE)
		m_pShareMemMap = mmap(NULL,tmpStat.st_size, PROT_READ | PROT_WRITE,MAP_SHARED,m_hShareMem,0);
	if(m_pShareMemMap == NULL || m_pShareMemMap == MAP_FAILED)
	{
		Loger.printf(LOG_ERROR,"[Shm_Open] mmap error=%s, shareName=%s, size=%d\n",strerror(errno), shmName, mem_size);
		return 0;
	}
	if(mem_size == DEFAULT_SIZE) //mummap -map 
	{
		memcpy(&mem_size, m_pShareMemMap, sizeof(int));
		Loger.printf(LOG_DEBUG,"[Shm_Open] change default size to =%d\n", mem_size);
		if(m_pShareMemMap != NULL)
		{
			if(munmap((void*)m_pShareMemMap, mem_size) < 0)
				Loger.printf(LOG_ERROR, "[Shm_Close] munmap Error! \n");
			else
				Loger.printf(LOG_DEBUG, "[Shm_Close] munmap OK!\n");    
		}
		
		if(ftruncate(m_hShareMem, mem_size) < 0)
		{
			Loger.printf(LOG_ERROR,"[Shm_Open] ftruncate error=%s, shareName=%s, size=%d\n", strerror(errno),shmName, mem_size);
			return 0;
		}
		memset(&tmpStat, 0, sizeof(tmpStat));
		if(fstat(m_hShareMem,&tmpStat) != 0)
		{
			Loger.printf(LOG_ERROR,"[Shm_Open] fstat error=%s, shareName=%s, size=%d\n",strerror(errno),shmName, mem_size);
			return 0;
		}	
		if(tmpStat.st_size != mem_size)
		{
			Loger.printf(LOG_WARNING,"[Shm_Open] tmpStat.st_size[%d] != mem_size[%d]\n", tmpStat.st_size, mem_size);
		}
		
		if(mode==READ_MODE)
			m_pShareMemMap = mmap(NULL,tmpStat.st_size,PROT_READ,MAP_SHARED,m_hShareMem,0);	
		else if(mode==WRITE_MODE)
			m_pShareMemMap = mmap(NULL,tmpStat.st_size, PROT_READ | PROT_WRITE,MAP_SHARED,m_hShareMem,0);

		if(m_pShareMemMap == NULL || m_pShareMemMap == MAP_FAILED)
		{
			Loger.printf(LOG_ERROR,"[Shm_Open] mmap error=%s, shareName=%s, size=%d\n",strerror(errno), shmName, mem_size);
			return 0;
		}
		
	}
	
	return 1;
}

int CShareMem::Shm_Read_Size(char * name)
{
/*
	char *p = (char*)m_pShareMemMap;
	int i_size;
	char size_buf[4]={0};
	memcpy(&i_size, p, 4);
	//i_size = (int)size_buf;
	return i_size;
*/
	return mem_size;
}

int CShareMem::Shm_Read_Value(const char * name, char * value)
{
	char buf_name[PARAM_NAME]={0};
	int	param_num=0;
	int i;
	char *p = (char*)m_pShareMemMap;
	param_num = (int)((mem_size -sizeof(int))/(PARAM_NAME + PARAM_VALUE));
	
	p+=sizeof(int);
	for(i=0;i<param_num;i++)
	{
		memset(buf_name, 0, sizeof(buf_name));
		memcpy(buf_name, p, sizeof(buf_name));
		if(strcmp(buf_name, name)==0)
		{
			memcpy(value, p+PARAM_NAME, PARAM_VALUE);
			Loger.printf(LOG_DEBUG, "[Shm_Read_Value] success, name=%s\n", name);
			return 1;
		}
		else
			p+=(PARAM_NAME+PARAM_VALUE);
	}
	Loger.printf(LOG_ERROR,"[Shm_Read_Value] error, name=%s\n", name);
	return 0;
}

int CShareMem::Shm_Write_Value(const char * name, const char * value)
{
	char buf_name[PARAM_NAME]={0};
	int	param_num=0;
	int i;
	char *p = (char*)m_pShareMemMap;
	param_num = (int)((mem_size -sizeof(int))/(PARAM_NAME + PARAM_VALUE));

	p+=sizeof(int);
	for(i=0;i<param_num;i++)
	{
		memset(buf_name, 0, sizeof(buf_name));
		memcpy(buf_name, p, sizeof(buf_name));
		if(strcmp(buf_name, name)==0)
		{
			memset(p+PARAM_NAME, 0, PARAM_VALUE);
			memcpy(p+PARAM_NAME, value, strlen(value)+1);
			Loger.printf(LOG_DEBUG, "[Shm_Write_Value] success, name=%s\n", name);
			return 1;
		}
		else
			p+=(PARAM_NAME+PARAM_VALUE);
	}
	Loger.printf(LOG_ERROR, "[Shm_Write_Value] error, name=%s\n", name);
	return 0;
}

int CShareMem::Shm_Close()
{
	
	if(m_pShareMemMap != NULL)
	{
		if(munmap((void*)m_pShareMemMap, mem_size) < 0)
			Loger.printf(LOG_ERROR, "[Shm_Close] munmap Error! \n");
		else
			Loger.printf(LOG_DEBUG, "[Shm_Close] munmap OK!\n");    
		m_pShareMemMap = NULL;
	}
	close(m_hShareMem);
	m_hShareMem = 0;

	return 1;
}



